home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / AppInstall / CoreMenu.py < prev    next >
Encoding:
Python Source  |  2009-03-31  |  8.8 KB  |  206 lines

  1. # (c) 2005-2007 Canonical - GPL
  2. # (c) 2006-2007 Sebastian Heinlein
  3. #
  4. # Authors:
  5. #  Michael Vogt
  6. #  Sebastian Heinlein
  7. #
  8.  
  9. import xdg.Menu
  10. import sys
  11. import os
  12. import pickle
  13. import glob
  14. from Util import *
  15. from gettext import gettext as _
  16.  
  17. class CoreApplicationMenu(object):
  18.     """This class provides basic menu handling that is required to
  19.        initialize the app-install cache"""
  20.  
  21.     debug = 0
  22.  
  23.     def __init__(self, datadir):
  24.         self.menudir = datadir+"/desktop"
  25.         # a set of seen desktop entries
  26.         self.desktopEntriesSeen = set()
  27.         # a dictonary that provides a mapping from a pkg to the
  28.         # application names it provides
  29.         self.pkg_to_app = {}
  30.         # cache
  31.         self.pickle = {}
  32.     self.popcon_max = 10
  33.         
  34.     def createMenuCache(self, targetdir, fname="menu.p"):
  35.         self.desktopEntriesSeen.clear()
  36.         self.pkg_to_app.clear()
  37.         for mpath in glob.glob(os.path.join(self.menudir, "*.menu")):
  38.             menu = xdg.Menu.parse(mpath)
  39.             self._populateFromEntry(menu)
  40.         pickle.dump(self.pickle, open('%s/%s' % (targetdir,fname),'w'), 2)
  41.  
  42.     def _populateFromEntry(self, node, parent=None, progress=None):
  43.         # for some reason xdg hiddes some entries, but we don't like that
  44.         for entry in node.getEntries(hidden=True):
  45.             self._dbg(2, "entry: %s" % (entry))
  46.             if isinstance(entry, xdg.Menu.Menu):
  47.                 # we found a toplevel menu
  48.                 name = xmlescape(entry.getName())
  49.                 self._dbg(1, "we have a sub-menu %s " % name)
  50.                 item = Category(self, name, entry.getIcon())
  51.                 #print "adding: %s" % name
  52.                 self.pickle[item] = []
  53.                 self._populateFromEntry(entry, item,  progress=progress)
  54.             elif isinstance(entry, xdg.Menu.MenuEntry):
  55.                 # more debug output
  56.                 self._dbg(3, node.getPath() + "/\t" + entry.DesktopFileID + "\t" + entry.DesktopEntry.getFileName())
  57.                 # we found a application
  58.                 name = xmlescape(entry.DesktopEntry.getName())
  59.                 self._dbg(1, "we have a application %s (%s) " % (name,entry.DesktopFileID))
  60.                 if name and entry.DesktopEntry.hasKey("X-AppInstall-Package"):
  61.                     self._dbg(2,"parent is %s" % parent.name)
  62.  
  63.                     # check for duplicates, caused by e.g. scribus that has:
  64.                     #   Categories=Application;Graphics;Qt;Office;
  65.                     # so it appears in Graphics and Office
  66.                     if entry.DesktopFileID in self.desktopEntriesSeen:
  67.                         #print "already seen %s (%s)" % (name, entry)
  68.                         continue
  69.                     self.desktopEntriesSeen.add(entry.DesktopFileID)
  70.  
  71.                     item = Application(name)
  72.                     # save the desktop entry to get the translations back later
  73.                     item.desktop_entry = entry.DesktopEntry
  74.                     pkgname = entry.DesktopEntry.get("X-AppInstall-Package")
  75.                     item.pkgname = pkgname
  76.                     # figure component and support status
  77.                     item.component = entry.DesktopEntry.get("X-AppInstall-Section")
  78.                     supported =  entry.DesktopEntry.get("X-AppInstall-Supported")
  79.                     if supported != "":
  80.                         item.supported = bool(supported)
  81.                     else:
  82.                         if item.component == "main" or \
  83.                                item.component == "restricted":
  84.                             item.supported = True
  85.                     # check for free software
  86.                     if item.component == "main" or item.component == "universe":
  87.                         item.free = True
  88.                     else:
  89.                         item.free = False
  90.                     # check for third party apps
  91.                     item.channel = entry.DesktopEntry.get("X-AppInstall-Channel")
  92.                     item.isv = entry.DesktopEntry.get("X-AppInstall-ISV")
  93.                     thirdparty =  entry.DesktopEntry.get("X-AppInstall-Proprietary")
  94.                     if thirdparty != "":
  95.                         item.thirdparty = bool(thirdparty)
  96.                         item.licenseUri = entry.DesktopEntry.get("X-AppInstall-LicenseUri")
  97.                     # Supported architectures
  98.                     archs = entry.DesktopEntry.get("X-AppInstall-Architectures", list=True)
  99.                     if archs:
  100.                         item.architectures.extend(archs)
  101.                     # save replaces (e.g. totem-gstreamer replaces totem-xine)
  102.                     replaces = entry.DesktopEntry.get("X-AppInstall-Replaces", list=True)
  103.                     if replaces:
  104.                         item.replaces = replaces
  105.                     # Icon
  106.                     item.iconname = entry.DesktopEntry.get("X-AppInstall-Icon", "") or entry.DesktopEntry.getIcon() or "applications-other"
  107.  
  108.                     if item.iconname.endswith(".png") or item.iconname.endswith(".xpm") or item.iconname.endswith(".svg"):
  109.                         item.iconname = item.iconname[:-4]
  110.                     item.comment = entry.DesktopEntry.getComment()
  111.                     item.mime = entry.DesktopEntry.get('MimeType', list=True)
  112.                     item.codecs = entry.DesktopEntry.get("X-AppInstall-Codecs").split(';')
  113.                     item.patentBadness = entry.DesktopEntry.get("X-AppInstall-PatentBadness", type='boolean')
  114.                     item.onTop = entry.DesktopEntry.get("X-AppInstall-AlwaysOnTop", type='boolean')
  115.                     
  116.                     # popcon data
  117.                     popcon_str = entry.DesktopEntry.get("X-AppInstall-Popcon")
  118.                     if popcon_str != "":
  119.                         popcon = int(popcon_str)
  120.                         item.popcon = popcon
  121.                         if popcon > self.popcon_max:
  122.                             self.popcon_max = popcon
  123.  
  124.                     item.execCmd = entry.DesktopEntry.getExec()
  125.                     item.needsTerminal = entry.DesktopEntry.getTerminal()
  126.                     # we map "Settings" to "Other" in the g-a-i GUI but 
  127.                     # not in the real gnome-menu. so do not display a
  128.                     # menu path here (FIXME: guess it from the category)
  129.                     if not "Settings" in entry.DesktopEntry.getCategories():
  130.                         item.menupath = [_("Applications"),parent.name]
  131.                     else:
  132.                         item.menupath = None
  133.                     self.pickle[parent].append(item)
  134.                 elif name:
  135.                     try:
  136.                         print "Skipped %s: not associated with a package" % entry
  137.                     except UnicodeEncodeError:
  138.                         pass
  139.                 else:
  140.                     try:
  141.                         print "Skipped %s: does not include a menu name" % entry
  142.                     except UnicodeEncodeError:
  143.                         pass
  144.  
  145.             elif isinstance(entry, xdg.Menu.Header):
  146.                 print "got header"
  147.  
  148.     def _dbg(self, level, msg):
  149.         """Write debugging output to sys.stderr."""
  150.         if level <= self.debug:
  151.             print >> sys.stderr, msg
  152.  
  153.  
  154.  
  155. class MenuItem(object):
  156.     " base class for a object in the menu "
  157.     def __init__(self, name, iconname="applications-other"):
  158.         # the name that is displayed
  159.         self.name = name
  160.         # the icon that is displayed
  161.         self.iconname = iconname
  162.         self.icontheme = None
  163.     def __repr__(self):
  164.         return "MenuItem: %s" % self.name
  165.  
  166. class Category(MenuItem):
  167.     """ represents a category """
  168.     def __init__(self, parent, name, iconname="applications-other"):
  169.         MenuItem.__init__(self, name, iconname)
  170.  
  171.  
  172. class Application(MenuItem):
  173.     """ this class represents a application """
  174.     def __init__(self, name, iconname="applications-other"):
  175.         MenuItem.__init__(self, name, iconname)
  176.         # the apt-pkg name that belongs to the app
  177.         self.pkgname = None
  178.         # the desktop file comment
  179.         self.comment = ""
  180.         # mime type
  181.         self.mime = None
  182.         # exec
  183.         self.execCmd = None
  184.         # needsTerminal
  185.         self.needsTerminal = False
  186.         # component the package is in (main, universe, multiverse, restricted)
  187.         self.component = None
  188.         # channel the pacakge is in (e.g. skype)
  189.         self.channel = None
  190.         # Name of the independent software vendor
  191.         self.isv = None
  192.         # states
  193.         self.popcon = 1            # the raw popcon data
  194.         self.rank = 1              # used by the ranking algo
  195.         self.onTop = False         # show always on top (regardless of rank/name)
  196.         # licence and support
  197.         self.free = False
  198.         self.licenseUri = None
  199.         self.supported = False
  200.         self.thirdparty = False
  201.         self.architectures = []
  202.         # textual menu path
  203.         self.menupath = ""
  204.         # install status
  205.         self.toInstall = None
  206.